package com.aviator.executor;


import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.function.AbstractVariadicFunction;
import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorDouble;
import com.googlecode.aviator.runtime.type.AviatorObject;
import com.googlecode.aviator.runtime.type.AviatorString;

import java.util.Map;

/**
 * @Author: Jiangxx
 * @Date: 2021/12/30
 * @Description: 自定义函数
 */
public class AviatorExecutor04 {

    public static void main(String[] args) {
        /* 注册函数 */
        AviatorEvaluator.addFunction(new AddFunction());
        AviatorEvaluator.addFunction(new GetFirstNonNullFunction());


        System.out.println(AviatorEvaluator.execute("add(1, 2)"));           // 3.0
        System.out.println(AviatorEvaluator.execute("add(add(1, 2), 100)")); // 103.0

        Long execute = (Long) AviatorEvaluator.execute("getFirstNonNull(1,2,3,4,nil,5)");
        System.out.println(execute);//1

        /* 自定义函数在 4.0.0　之后也可以通过 lambda　来定义 */
        AviatorEvaluator.defineFunction("add1", "lambda (x,y) -> x + y end");
        Long result = (Long) AviatorEvaluator.exec("add1(1,2)");
        System.out.println(result);
    }
}

/**
 * Aviator 除了内置的函数之外,还允许用户自定义函数,只要实现com.googlecode.aviator.runtime.type.AviatorFunction接口,
 * 并注册到AviatorEvaluator即可使用. AviatorFunction接口十分庞大, 通常来说你并不需要实现所有的方法,
 * 只要根据你的方法的参数个数, 继承AbstractFunction类并override相应方法即可。
 *
 * 定义一个参数确定的自定函数，需继承AbstractFunction
 */
class AddFunction extends AbstractFunction {

    /**
     * 自定义参数确定的函数实现
     * @param env
     * @param arg1
     * @param arg2
     * @return
     */
    @Override
    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
        Number left = FunctionUtils.getNumberValue(arg1, env);
        Number right = FunctionUtils.getNumberValue(arg2, env);
        return new AviatorDouble(left.doubleValue() + right.doubleValue());
    }

    /**
     * 函数名
     * @return
     */
    @Override
    public String getName() {
        return "add";
    }
}

/**
 * 定义一个参数不确定的自定义函数，需继承AbstractVariadicFunction
 */
class GetFirstNonNullFunction extends AbstractVariadicFunction {

    @Override
    public AviatorObject variadicCall(Map<String, Object> map, AviatorObject... aviatorObjects) {
        if (aviatorObjects != null) {
            for (AviatorObject aviatorObject : aviatorObjects) {
                if (aviatorObject.getValue(map) != null) {
                    return aviatorObject;
                }
            }
        }
        return new AviatorString(null);
    }

    @Override
    public String getName() {
        return "getFirstNonNull";
    }
}
